#include "fxcc/core/graph/common/BoneNode.h"

using namespace fxcc::graph::common;

BoneNode::BoneNode(const fxcc::graph::common::Scene *scene)
	: m_RootNode(scene->m_RootNode.get())
{

	if (!CreateFrom(scene->m_RootNode.get()))
	{
		ztclog::info("Failed create boneNode");
	}
};
fxcc::graph::common::BoneNode::BoneNode(const fxcc::graph::common::Node * node, const std::map<std::string,Bone>& bones)
{
}

bool BoneNode::CreateFrom(const Node *node)
{
	m_NodeName = node->m_Name;
	m_NodeOffset = node->m_Offset;
	m_NodeTransform = node->m_Offset;

	const auto &it = m_Bones.find(m_NodeName);
	if (it != m_Bones.end())
	{
		this->m_BoneOffset = it->second.m_OffsetMatrix;
		this->m_BoneIndex = it->second.m_Index;
		this->m_NodeTransform = this->m_NodeOffset;
	}

	for (const auto &child : node->m_Childern)
	{
		this->children.push_back(std::make_shared<BoneNode>(child.get(), m_Bones));
	}
	return true;
};

void BoneNode::ProcessNode(fxcc::graph::common::Transform parentModel)
{

	fxcc::graph::common::Transform globalModel(parentModel * m_NodeTransform.GetWorld());

	if (this->m_BoneIndex != -1)
	{
		this->m_BoneFinal = globalModel * this->m_BoneOffset;
	}
	for (auto &child : children)
	{
		child->ProcessNode(globalModel);
	}
};

void BoneNode::UpdateBuffer(fxcc::graph::common::Effect3d::BoneData &target)
{
	if (this->m_BoneIndex != -1)
	{
		target.bones[this->m_BoneIndex] = this->m_BoneFinal.GetWorld();
	}
	for (auto &child : children)
	{
		child->UpdateBuffer(target);
	}
}

void BoneNode::LoadLocalTransform(const fxcc::graph::common::ChannelDataSet *channelDataSet)
{

	if (channelDataSet->HasBone(this->m_NodeName))
	{
		auto it = channelDataSet->m_ChannalDataMaps.find(m_NodeName);
		const auto &nodeTransform = it->second.m_LocalTransform;

		this->m_NodeTransform = nodeTransform;
	};
	for (const auto child : children)
	{
		child->LoadLocalTransform(channelDataSet);
	};
};
